//
// Created by 11510 on 2024/6/17.
//
#include <iostream>
#include <string>
#include <cstring>
using namespace std;

class Base{
public:
    explicit Base(const char* base): base(new char[strlen(base) + 1]()){
        strcpy(this->base, base);
    }
    Base(const Base& rhs): base(new char[strlen(rhs.base) + 1]()){
        strcpy(base, rhs.base);
    }

    void print() const{
        printf("base = %s\n", base);
    }

    Base& operator=(const Base& rhs){
        if(&rhs != this) {
            delete[] base;
            base = new char[ strlen(rhs.base) + 1]();
            strcpy(base, rhs.base);
        }
        return *this;
    }

    ~Base(){
        if(base != nullptr){
            delete[] base;
            base = nullptr;
        }
    }

    char* base;
};

class Derived:public Base{
public:
    Derived(const char* base, long derived, const char* str): Base(base),_derived(derived), _str(new char[strlen(str) + 1]()){
        strcpy(_str, str);
    }

    Derived(const Derived& rhs): Base(rhs), _derived(rhs._derived), _str(new char[strlen(rhs._str) + 1]()){
        strcpy(_str, rhs._str);
        printf("derived拷贝构造\n");
    }

    /* 自复制只在有指针指向堆内存时用 */
    Derived& operator=(const Derived& rhs){
        printf("derived赋值\n");
        if(&rhs != this){
            Base::operator=(rhs);

//            BUG
            /* 此处会有潜在的double free */
            delete [] _str;
            _str = new char[strlen(rhs._str) + 1]();
            strcpy(_str,rhs._str);
            _derived = rhs._derived;

            _derived = rhs._derived;
        }
        return *this;
    }

    ~Derived(){
        if(_str){
            delete [] _str;
            _str = nullptr;
        }
    }

    void display()const{
        printf("display %ld\n", _derived);
    }
private:
    long _derived = 12;
    char* _str;
};




void test1(){
    Derived d1("hello",7,"beijing");

    /* 这里是调用拷贝构造不是赋值 */
    Derived d2 = d1;
//    d2.print();
//
    Derived d3("world",5,"shanghai");
    d1 = d3;
//    d1.print();
}


int main() {
    test1();
    return 0;
}
